package com.blog.web.controller.user;

import com.blog.common.core.controller.BaseController;
import com.blog.common.core.domain.AjaxResult;
import com.blog.common.core.domain.entity.SysDept;
import com.blog.common.core.domain.entity.SysUser;
import com.blog.common.utils.DateUtils;
import com.blog.common.utils.ShiroUtils;
import com.blog.common.utils.StringUtils;
import com.blog.common.utils.UserAuthenticationUtils;
import com.blog.framework.shiro.service.SysPasswordService;
import com.blog.system.domain.*;
import com.blog.system.domain.req.CancelOrderDto;
import com.blog.system.domain.req.TableReq;
import com.blog.system.domain.req.UserDto;
import com.blog.system.domain.res.*;
import com.blog.system.domain.user.dto.UserNameDto;
import com.blog.system.domain.user.dto.UserSubmit;
import com.blog.system.domain.user.dto.UserUpdate;
import com.blog.system.service.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.blog.common.core.domain.AjaxResult.error;
import static com.blog.common.core.domain.AjaxResult.success;

@RequestMapping("user")
@RestController
public class UserController extends BaseController {

    @Autowired
    private SysPasswordService passwordService;
    @Autowired
    private IRoomTimeService roomTimeService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private UserService userService1;


    /**
     * 用户端注册
     */
    @PostMapping("/register")
    public AjaxResult register(@RequestBody UserDto user) {
        if (!userService1.existsByUsername(user.getUsername())) {
            return AjaxResult.error("用户名已存在");
        }
//
        // 2. 校验手机号格式和是否存在
        if (!user.getPhone().matches("^1[3-9]\\d{9}$")) {
            return AjaxResult.error("手机号格式错误");
        }
        if (!userService1.existsByPhone(user.getPhone())) {
            return AjaxResult.error("手机号已注册");
        }
        //保存用户信息
        User user1 = new User();
        user1.setUserName(user.getUsername());
        user1.setPassword(user.getPassword());
        user1.setPhone(user.getPhone());
        user1.setCreateTime(LocalDateTime.now());
        user1.setUpdateTime(LocalDateTime.now());
        userService1.insertUser(user1);
        return AjaxResult.success();
    }

    /**
     * 用户端登录
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody WxLoginRequest request) {
        User userByUsername = userService1.getUserByUsername(request.getUsername());
        if (userByUsername == null) {
            return AjaxResult.error("用户未注册");
        }
        if (userByUsername.getPassword().equals(request.getPassword())) {
            return AjaxResult.success(request.getUsername());
        } else {
            return AjaxResult.error("密码/用户名不正确");
        }
    }

    @PostMapping("/submit")
    public AjaxResult submitReserve(@RequestBody UserSubmit request) {
        boolean isConflict = roomTimeService.checkConflict(request.getRoomId(), request.getSeatId(),
                request.getStartTime(), request.getStopTime());
        if (isConflict) {
            return AjaxResult.error("该时间段已被预约");
        }
        //todo 金额扣除 判断金钱够不够
        RoomTime roomTime = new RoomTime();
        roomTime.setRoomId(request.getRoomId());
        roomTime.setStartTime(request.getStartTime());
        roomTime.setStopTime(request.getStopTime());
        roomTime.setData(request.getDate());
        roomTime.setUserId(request.getUser_id());
        roomTime.setCreate_time(LocalDateTime.now());
        roomTime.setUpdate_time(LocalDateTime.now());
        roomTime.setCount(request.getCount().toString());
        roomTime.setSeatId(request.getSeatId());
        roomTime.setRoomName(request.getRoomName());//座位名称 没改名字
        roomTimeService.insertRoomTime(roomTime);
        return AjaxResult.success("预定成功");
    }

    @PostMapping("/updateRoom")
    public AjaxResult updateRoom(@RequestBody UserUpdate request) {

        boolean isConflict = roomTimeService.checkConflict(request.getRoomId(), request.getSeatId(),
                request.getStartTime(), request.getStopTime());
        if (isConflict) {
            return AjaxResult.error("该时间段已被预约");
        }
        //todo 金额补回 先返回在扣除 判断金钱够不够
        roomTimeService.deleteRoomTimeById(Long.parseLong(request.getId()));
        RoomTime roomTime = new RoomTime();
        roomTime.setRoomId(request.getRoomId());
        roomTime.setStartTime(request.getStartTime());
        roomTime.setStopTime(request.getStopTime());
        roomTime.setData(request.getDate());
        roomTime.setUserId(request.getUser_id());
        roomTime.setCreate_time(LocalDateTime.now());
        roomTime.setUpdate_time(LocalDateTime.now());
        roomTime.setCount(request.getCount().toString());
        roomTime.setSeatId(request.getSeatId());

        roomTimeService.insertRoomTime(roomTime);
        return AjaxResult.success("预定成功");
    }

    /**
     * 取消预定
     */
    @PostMapping("/deleteRoom")
    public AjaxResult deleteRoom(@RequestBody UserUpdate request) {
        roomTimeService.deleteRoomTimeById(Long.parseLong(request.getId()));
        //todo 金额返回 需要增加金额表
        return AjaxResult.success("取消成功");
    }

    /**
     * 预定历史 只给最近四个
     */
    @PostMapping("/ReservationHistory")
    public AjaxResult ReservationHistory() {
        Subject currentUser = SecurityUtils.getSubject();
        if (currentUser.isAuthenticated()) {
            // 获取当前登录用户的 principal，通常是用户名
            String username = (String) currentUser.getPrincipal();
            // 根据用户名从数据库中查询用户详细信息
//            SysUser user = userService.selectUserByUserName(username);
//            if (user != null) {
            // 查找用户预定过得自习室
            List<RoomTime> reservedRooms = roomTimeService.getRoomsByUserName(username);
            return AjaxResult.success(reservedRooms);
//            }
        }
        return AjaxResult.error("未登录或无法获取用户信息");
    }


    /**
     * 猜你喜欢
     */
    @PostMapping("/recommend")
    public AjaxResult submitReserve(@RequestBody UserNameDto userNameDto) {
        List<RoomTime> roomsByUserName = roomTimeService.getRoomsByUserName(userNameDto.getUserName());
        List<RoomTime> roomTimes = guessYouLike(roomsByUserName);
        RecommendListRes recommendListRes = new RecommendListRes();
        List<RecommendRes> list = new ArrayList<>();
        roomTimes.forEach(roomTime -> {
            RecommendRes recommendRes = new RecommendRes();
            recommendRes.setSeatId(roomTime.getSeatId());
            recommendRes.setSeatName(roomTime.getRoomName());
            recommendRes.setRoomId(roomTime.getRoomId());
            recommendRes.setBack("/images/recommend-1.jpg");
            list.add(recommendRes);
        });
        recommendListRes.setRecommendRes(list);
        return AjaxResult.success(recommendListRes);
    }

    @PostMapping("/historyOrders")
    public AjaxResult historyOrders(@RequestBody UserNameDto userNameDto) {
        List<RoomTime> roomsByUserName = roomTimeService.getRoomsByUserName(userNameDto.getUserName());
        roomsByUserName.sort((o1, o2) -> o1.getCreateTime().compareTo(o2.getCreateTime()));
        List<OrderRes> list = new ArrayList<>();
        roomsByUserName.forEach(vo -> {
            OrderRes orderRes = new OrderRes();
            orderRes.setId(Integer.valueOf(vo.getId().toString()));
            orderRes.setRoomId(vo.getRoomId());
            orderRes.setSeatId(vo.getSeatId());
            orderRes.setPayment(vo.getCount());
            orderRes.setSeatName(vo.getRoomName());
            orderRes.setStartTime(vo.getStartTime().toString());
            orderRes.setEndTime(vo.getStopTime().toString());
            int status = 0;
            if (vo.getStartTime().isAfter(LocalDateTime.now())) {
                status = 1;
            } else if (vo.getStartTime().isBefore(LocalDateTime.now())) {
                status = 2;
            }
            orderRes.setStatus(status);
            list.add(orderRes);
        });
        return AjaxResult.success(list);
    }

    /**
     * 取消预约
     */
    @PostMapping("cancelOrder")
    public AjaxResult cancelOrder(@RequestBody CancelOrderDto cancelOrderDto) {
        roomTimeService.deleteRoomTimeById(Long.parseLong(cancelOrderDto.getOrderId()));
        return AjaxResult.success("取消成功");

    }

    /**
     * 个人中心
     */
    @PostMapping("/userInfo")
    public AjaxResult userInfo(@RequestBody UserNameDto userNameDto) {
        User userByUsername = userService1.getUserByUsername(userNameDto.getUserName());
        UserRes userRes = new UserRes();
        userRes.setNickName(userByUsername.getUserName());
        return AjaxResult.success(userRes);
    }

    /**
     * 座位列表
     */
    @PostMapping("/tableList")
    public AjaxResult tableList(@RequestBody TableReq tableReq) {
        List<SysDept> sysDepts = deptService.selectTable(tableReq.getRoomId());
        TableListRes tableListRes = new TableListRes();
        List<TableRes> list = new ArrayList<>();
        sysDepts.forEach(vo -> {
            TableRes tableRes = new TableRes();
            tableRes.setSeatId(vo.getDeptId().toString());
            tableRes.setAvailable(true);
            tableRes.setHasPower(true);
            tableRes.setSeatType("1");
            tableRes.setSeatName(vo.getDeptName());
            list.add(tableRes);
        });
        tableListRes.setTableResList(list);
        return AjaxResult.success(tableListRes);
    }

    /**
     * 自习室类型列表
     */
    @PostMapping("/roomList")
    public AjaxResult roomList() {

        List<SysDept> sysDepts = deptService.selectRoom();
        RoomListRes roomListRes = new RoomListRes();
        List<RoomRes> list = new ArrayList<>();
        sysDepts.forEach(vo -> {
            RoomRes roomRes = new RoomRes();
            roomRes.setRoomId(vo.getDeptId().toString());
            roomRes.setRoomType("1");
            roomRes.setRoomName(vo.getDeptName());
            list.add(roomRes);
        });
        roomListRes.setRoomResList(list);
        return AjaxResult.success(roomListRes);
    }


    /**
     * 学习时长
     */
    @PostMapping("/learnTime")
    public AjaxResult learnTime(@RequestBody UserNameDto userNameDto) {
        String studyLength = roomTimeService.getStudyLength(userNameDto.getUserName());
        String avgDaily = roomTimeService.getAvgDaily(userNameDto.getUserName());
        StudyMessageRes studyMessageRes = new StudyMessageRes();
        studyMessageRes.setLength(studyLength + "小时");
        studyMessageRes.setAvgDaily(avgDaily + "天");
        double v = Double.parseDouble(avgDaily);
        double v1 = Double.parseDouble(studyLength);
        studyMessageRes.setFocusPercent(String.valueOf((v1 / v)));

        return AjaxResult.success(studyMessageRes);
    }

    //    /**
//     * 已经学习了多少天
//     */
//    @PostMapping("/learnDay")
//    public AjaxResult learnDay() {
//        Subject currentUser = SecurityUtils.getSubject();
//        if (currentUser.isAuthenticated()) {
//            // 获取当前登录用户的 principal，通常是用户名
//            String username = (String) currentUser.getPrincipal();
//            // 查找用户预定过得自习室
//            List<RoomTime> reservedRooms = roomTimeService.getRoomsByUserName(username);
//            return AjaxResult.success(reservedRooms.size());
//        }
//        return AjaxResult.error("未登录或无法获取用户信息");
//    }
    public List<RoomTime> guessYouLike(List<RoomTime> userHistory) {
        // 1. 无历史数据时返回空列表（或填充默认数据）
        if (userHistory.isEmpty()) {
            return Collections.emptyList();
        }

        // 2. 统计用户偏好：最常预约的自习室名称和最常预约的小时段（小时）
        Map<String, Integer> roomNameCount = new HashMap<>();
        Map<Integer, Integer> hourCount = new HashMap<>();

        for (RoomTime record : userHistory) {
            // 统计自习室名称出现次数
            String roomName = record.getRoomName();
            roomNameCount.put(roomName, roomNameCount.getOrDefault(roomName, 0) + 1);

            // 统计常用时间段（按小时）
            int hour = record.getStartTime().getHour();
            hourCount.put(hour, hourCount.getOrDefault(hour, 0) + 1);
        }

        // 3. 获取用户最常选的自习室名称和时段
        String favoriteRoom = roomNameCount.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse("");

        Integer favoriteHour = hourCount.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse(-1);

        // 4. 生成推荐逻辑（直接复用历史数据）
        List<RoomTime> recommendations = new ArrayList<>();
        for (RoomTime room : userHistory) {
            // 规则1：匹配最常去的自习室名称
            boolean matchRoom = room.getRoomName().contains(favoriteRoom);

            // 规则2：匹配最常预约的小时段
            boolean matchHour = room.getStartTime().getHour() == favoriteHour;

            // 规则3：随机推荐（避免无结果）
            boolean randomPick = new Random().nextInt(10) < 3; // 30%概率随机选

            if (matchRoom || matchHour || randomPick) {
                recommendations.add(room);
            }
        }

        // 5. 去重、打乱顺序、限制数量
        return recommendations.stream()
                .distinct()
                .sorted((a, b) -> new Random().nextInt(2) - 1) // 随机打乱
                .limit(3)
                .collect(Collectors.toList());
    }

}
